namespace FIREFLYX {
    export class GLBProcessor implements IAssetProcessor {
        public Type: AssetType = AssetType.GLB;
        public suffix: string = ".glb";
        public rawType: XMLHttpRequestResponseType = "arraybuffer";
        public parse(data: ArrayBuffer, filePath: string): Nullable<Asset> {
            //解析GLB 
            const HEADER_MAGIC = "glTF";
            const HEADER_LENGTH = 12;
            const CHUNK_TYPES_BIN = 0x004E4942;
            const CHUNK_TYPES_JSON = 0x4E4F534A;

            const headerView = new DataView(data, 0, HEADER_LENGTH);
            const header = {
                magic: decodeUtf8(new Uint8Array(data.slice(0, 4))),
                version: headerView.getUint32(4, true),
                length: headerView.getUint32(8, true)
            };

            //检查 data 是否是有效的 GLB 格式 ，版本是否支持
            if (header.magic !== HEADER_MAGIC) {
                throw new Error(`Unsupported glTF-Binary header. `);
            } else if (header.version < 2.0) {
                throw new Error(`Legacy binary file detected.`);
            }

            //分解块数据
            const chunkContentsLength = header.length - HEADER_LENGTH;
            const chunkView = new DataView(data, HEADER_LENGTH);
            let chunkIndex = 0;
            let gltfJsonText: string = "";
            let binData: Nullable<ArrayBuffer> = null;
            while (chunkIndex < chunkContentsLength) {
                const chunkLength = chunkView.getUint32(chunkIndex, true);
                chunkIndex += 4;
                const chunkType = chunkView.getUint32(chunkIndex, true);
                chunkIndex += 4;

                if (chunkType === CHUNK_TYPES_JSON) {

                    const contentArray = new Uint8Array(data, HEADER_LENGTH + chunkIndex, chunkLength);
                    gltfJsonText = decodeUtf8(contentArray);

                } else if (chunkType === CHUNK_TYPES_BIN) {

                    const byteOffset = HEADER_LENGTH + chunkIndex;
                    binData = data.slice(byteOffset, byteOffset + chunkLength);

                } // Clients must ignore chunks with unknown types.

                chunkIndex += chunkLength;
            }

            //解析path
            const _idx = filePath.lastIndexOf("/");
            const filename = filePath.substring(_idx + 1);
            const gltfPath = filePath.substring(0, _idx + 1);
            //保存bin 到AssetManager
            const binName = `${GLTF.BIN_TAG}0`;
            const bin = new BinaryData(binName);
            bin.buffer = binData as ArrayBuffer;
            const bufPath = `${gltfPath}${binName}`;
            AssetManager.SetAsset(bufPath, bin);
            //gltfJSON 数据解析
            const gltfJson = JSON.parse(gltfJsonText);

            //gltf 资源
            const gltf = new GLTF(filename);
            gltf.setData(gltfJson, gltfPath);
            return gltf;
        }
    }
}